﻿/*
 * LdResponseDocument
 * 
 * initial implementation : 26.6.2013
 *
 * Copyright (c) Adam Sida, asida@centrum.cz.
 * All rights reserved.
 * 
 * for license see cz.uhul.DSMLv2.txt
 */
using System;
using System.Collections.Generic;
using System.Web;
using System.Xml;
using System.Xml.Schema;
using System.Xml.XPath;
using System.Xml.Serialization;
//using System.ServiceModel;


namespace cz.uhul.DSMLv2
{

  /// <summary>
  /// reimplements M$ DsmlResponseDocument, assholes did crapy sealed code...
  /// </summary>
  [XmlRoot(ElementName = "batchResponse", Namespace = "urn:oasis:names:tc:DSML:2:0:core")]
  [XmlInclude(typeof(LdAuthResponse))]
  //[MessageContract(WrapperName = "batchResponse")]
  public class LdResponseDocument : LdDocument
  {


    public LdResponseDocument()
    {

      ModifyResponses = new LdModifyResponseCollection();
      SearchResponses = new LdSearchResponseCollection();
      AddResponses = new LdAddResponseCollection();
      DeleteResponses = new LdDeleteResponseCollection();
      ModifyDnResponses = new LdModifyDnResponseCollection();
      CompareResponses = new LdCompareResponseCollection();
      ExtendedResponses = new LdExtendedResponseCollection();
      
    }


    ///// <summary>
    ///// The System.DirectoryServices.Protocols.DsmlResponseDocument.IsOperationError
    ///// property specifies whether an operation error response has occurred.
    ///// </summary>
    //[XmlIgnore]
    //public bool IsOperationError { get; protected set; }




    ///// <summary>
    ///// The System.DirectoryServices.Protocols.DsmlResponseDocument.IsErrorResponse
    ///// property specifies whether an error response has occurred.
    ///// </summary>
    //[XmlIgnore]
    //public bool IsErrorResponse { get; protected set; }





    [XmlElement(ElementName = "authResponse", Form = XmlSchemaForm.None, IsNullable = false)]
    public LdAuthResponse AuthResponse { get; set; }




    [XmlElement(ElementName = "modifyResponse", Form = XmlSchemaForm.None, IsNullable = true)]
    public LdModifyResponseCollection ModifyResponses { get; set; }





    [XmlElement(ElementName = "searchResponse", Form = XmlSchemaForm.None, IsNullable = true)]
    public LdSearchResponseCollection SearchResponses { get; set; }





    [XmlElement(ElementName = "addResponse", Form = XmlSchemaForm.None, IsNullable = true)]
    public LdAddResponseCollection AddResponses { get; set; }





    [XmlElement(ElementName = "delResponse", Form = XmlSchemaForm.None, IsNullable = true)]
    public LdDeleteResponseCollection DeleteResponses { get; set; }





    [XmlElement(ElementName = "modDNResponse", Form = XmlSchemaForm.None, IsNullable = true)]
    public LdModifyDnResponseCollection ModifyDnResponses { get; set; }





    [XmlElement(ElementName = "compareResponse", Form = XmlSchemaForm.None, IsNullable = true)]
    public LdCompareResponseCollection CompareResponses { get; set; }





    [XmlElement(ElementName = "extendedResponse", Form = XmlSchemaForm.None, IsNullable = true)]
    public LdExtendedResponseCollection ExtendedResponses { get; set; }




    public XmlDocument ToXml()
    {
      XmlDocument outDoc = new XmlDocument();

      XPathNavigator nav = outDoc.CreateNavigator();

      XmlWriter writer = nav.AppendChild();

      XmlSerializer xs = new XmlSerializer(typeof(LdResponseDocument), "urn:oasis:names:tc:DSML:2:0:core");
      xs.Serialize(writer, this);

      writer.Close();

      //// Memorise and remove the element we want
      //XmlNode infoNode = outDoc.FirstChild;
      //outDoc.RemoveChild(infoNode);

      //// Move into a root <detail> element
      //var rootNode = outDoc.AppendChild(outDoc.CreateNode(XmlNodeType.Element, "detail", ""));
      //rootNode.AppendChild(infoNode);

      return outDoc;
    }




    //public Message ToMessage(MessageVersion ver, string op)
    //{
    //  return Message.CreateMessage(ver, op, new XmlNodeReader( ToXml()) );
    //}





    /// <summary>
    /// parses DSML document from input <c>XmlDocument</c>
    /// </summary>
    /// <param name="doc"></param>
    /// <returns></returns>
    public static LdResponseDocument Parse(object data)
    {
      XmlDocument xdoc;

      if (data is XmlDocument)
        return LdResponseDocument.Parse((XmlDocument)data);

      else if(data is XmlElement)
        return LdResponseDocument.Parse((XmlElement)data);

      else if (data is string)
      {
        xdoc = new XmlDocument();
        xdoc.LoadXml((string)data);
        return LdResponseDocument.Parse(xdoc);
      }
      //else if (doc is Message)
      //{
      //  xdoc = new XmlDocument();
      //  XPathNavigator nav = xdoc.CreateNavigator();

      //  XmlDictionaryWriter writer = XmlDictionaryWriter.CreateDictionaryWriter(nav.AppendChild());
      //  ((Message)doc).WriteBody(writer);

      //  writer.Close();

      //  return LdResponseDocument.Parse(xdoc);
      //}
      else if(data is XmlDictionaryReader)
      {
        return LdResponseDocument.Parse((XmlReader)data);
      }

      else
        throw new LdException("LdResponseDocument.Parse error, invalid input of type:" + data.GetType().ToString());
        //return null;

    }




    /// <summary>
    /// parses DSML document from input <c>XmlDocument</c>
    /// </summary>
    /// <param name="doc"></param>
    /// <returns></returns>
    public static LdResponseDocument Parse(XmlElement docElm)
    {

      //System.Xml.Linq.XDocument xdoc = System.Xml.Linq.XDocument.  Load(@"test.xml");
      //var tabs = xdoc.Descendants("Tab")
      //              .OrderBy(t => Convert.ToInt32(t.Attribute("Order").Value))
      //              .ToList();

      XmlSerializer srl = new XmlSerializer(typeof(LdResponseDocument), "urn:oasis:names:tc:DSML:2:0:core");

      XmlNodeReader reader = new XmlNodeReader(docElm);
      //srl.UnknownAttribute += new XmlAttributeEventHandler(i1);
      //srl.UnknownElement += new XmlElementEventHandler(i2); 
      //srl.UnknownNode += new XmlNodeEventHandler(i3);
      //srl.UnreferencedObject += new UnreferencedObjectEventHandler(i4);

      if (!srl.CanDeserialize(reader))
        throw new ArgumentException("errror parsing LdResponseDocument");

      LdResponseDocument tmpDoc = (LdResponseDocument)srl.Deserialize(reader);

      return tmpDoc;

    }





    /// <summary>
    /// parses DSML document from input <c>XmlDocument</c>
    /// </summary>
    /// <param name="doc"></param>
    /// <returns></returns>
    public static LdResponseDocument Parse(XmlDocument doc)
    {

      //System.Xml.Linq.XDocument xdoc = System.Xml.Linq.XDocument.  Load(@"test.xml");
      //var tabs = xdoc.Descendants("Tab")
      //              .OrderBy(t => Convert.ToInt32(t.Attribute("Order").Value))
      //              .ToList();

      XmlSerializer srl = new XmlSerializer(typeof(LdResponseDocument), "urn:oasis:names:tc:DSML:2:0:core");

      XmlNodeReader reader = new XmlNodeReader(doc.DocumentElement);
      //srl.UnknownAttribute += new XmlAttributeEventHandler(i1);
      //srl.UnknownElement += new XmlElementEventHandler(i2); 
      //srl.UnknownNode += new XmlNodeEventHandler(i3);
      //srl.UnreferencedObject += new UnreferencedObjectEventHandler(i4);

      if (!srl.CanDeserialize(reader))
        throw new ArgumentException("errror parsing LdResponseDocument");

      LdResponseDocument tmpDoc = (LdResponseDocument)srl.Deserialize(reader);

      return tmpDoc;

    }





    /// <summary>
    /// parses DSML document from input <c>XmlReader</c>
    /// </summary>
    /// <param name="data">input data in XmlReader on specific position</param>
    /// <returns></returns>
    public static LdResponseDocument Parse(XmlReader reader)
    {

      //XmlDocument debug = new XmlDocument();
      //debug.Load(reader);

      XmlSerializer srl = new XmlSerializer(typeof(LdResponseDocument), "urn:oasis:names:tc:DSML:2:0:core");

      //if (!srl.CanDeserialize(reader))
      //  throw new ArgumentException("errror parsing LdResponseDocument");

      LdResponseDocument tmpDoc = (LdResponseDocument)srl.Deserialize(reader);

      return tmpDoc;

    }




    public XmlReader ToXmlReader()
    {
      return new XmlNodeReader(this.ToXml());
    }


  }

}